/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @file file_session.c
 * pyhp session file backend
 */

#include <time.h>
#include <apr_strings.h>

#include "file_session.h"
#include "config.h"
#include "pyhp_layer.h"

int pyhp_session_file_save(PyHPData *pydata, char const *id, char const *content)
{
    request_rec *r = pyhp_layer_get_internal(pydata, "apache_request");
    pyhp_config *cfg = pyhp_get_config(r);
    char *session_filename = apr_pstrcat(r->pool, cfg->session_path, id, NULL);

    pyhp_logf(r, PyHP_DEBUG, "Saving session on %s", session_filename);

    apr_size_t size = strlen(content);
    apr_file_t *file;

    if (apr_file_open(&file, session_filename, APR_CREATE|APR_WRITE, APR_OS_DEFAULT, r->pool) != APR_SUCCESS) {
        pyhp_logf(r, PyHP_ERR, "Failed saving session %s", id);
        return 0;
    }

    apr_file_write(file, content, &size);
    apr_file_close(file);
    return 1;
}

void pyhp_session_file_wipe(PyHPData *pydata, char const *id)
{
    request_rec *r = pyhp_layer_get_internal(pydata, "apache_request");
    pyhp_config *cfg = pyhp_get_config(r);

    char *path = apr_pstrcat(r->pool, cfg->session_path, id, NULL);
    unlink(path);
}

int pyhp_session_file_check_if_exists(PyHPData *pydata, char const *id)
{
    request_rec *r = pyhp_layer_get_internal(pydata, "apache_request");
    pyhp_config *cfg = pyhp_get_config(r);

    char *session_filename = apr_pstrcat(r->pool, cfg->session_path, id, NULL);
    struct stat stat_result;

    if (stat(session_filename, &stat_result) == 0) {
        time_t now_t = time(NULL);
        if ( (stat_result.st_mtime + (60*pyhp_config_sesstimeout(r))) < now_t ) {
            pyhp_logf(r, PyHP_DEBUG, "Session %s is expired...", id);
            unlink(session_filename);
            return 0;
        }
        else {
            pyhp_logf(r, PyHP_DEBUG, "Session %s exists...", id);
            return 1;
        }
    }

    pyhp_logf(r, PyHP_WARN, "Session %s does not exist (%s)", id, strerror(errno));
    return 0;
}

PyObject *pyhp_session_file_load(PyHPData *pydata, char const *id)
{
    request_rec *r = pyhp_layer_get_internal(pydata, "apache_request");
    pyhp_config *cfg = pyhp_get_config(r);
    struct stat file_info;
    apr_file_t *file;
    apr_mmap_t *file_content;
    PyObject *session_data;

    char *filename = apr_pstrcat(r->pool, cfg->session_path, id, NULL);

    if (apr_file_open(&file, filename, APR_READ, APR_OS_DEFAULT, r->pool) != APR_SUCCESS) {
        pyhp_log(r, PyHP_ERR, "Fatal Error: impossible to open the session file even if it exists");
        return NULL;
    }
    else {
        lstat(filename, &file_info);
        apr_mmap_create(&file_content, file, 0, file_info.st_size,
                        APR_MMAP_READ, r->pool);

        session_data = pyhp_layer_unpack_object(pydata, file_content->mm);

        apr_mmap_delete(file_content);
        apr_file_close(file);

        return session_data;
    }
}
